using Reflector.CodeModel;

namespace LanguageWriterHelper
{
    public class ExpressionVisitor : VisitorBase
    {
        
        public void Visit(IExpression value)
        {
            if (value == null)
                return;
                        
            Visit(value as IAddressDereferenceExpression);
            Visit(value as IAddressOfExpression);
            Visit(value as IAddressOutExpression);
            Visit(value as IAddressReferenceExpression);
            Visit(value as IAnonymousMethodExpression);
            Visit(value as IArgumentListExpression);
            Visit(value as IArgumentReferenceExpression);
            Visit(value as IArrayCreateExpression);
            Visit(value as IArrayIndexerExpression);
            Visit(value as IAssignExpression);
            Visit(value as IBaseReferenceExpression);
            Visit(value as IBinaryExpression);
            Visit(value as IBlockExpression);
            Visit(value as ICanCastExpression);
            Visit(value as ICastExpression);
            Visit(value as IConditionExpression);
            Visit(value as IDelegateCreateExpression);
            Visit(value as IDelegateInvokeExpression);
            Visit(value as IEventReferenceExpression);
            Visit(value as IFieldReferenceExpression);
            Visit(value as IFieldOfExpression);
            Visit(value as IGenericDefaultExpression);
            Visit(value as ILambdaExpression);
            Visit(value as ILiteralExpression);
            Visit(value as IMemberInitializerExpression);
            Visit(value as IMethodInvokeExpression);
            Visit(value as IMethodOfExpression);
            Visit(value as IMethodReferenceExpression);
            Visit(value as INullCoalescingExpression);
            Visit(value as IObjectCreateExpression);
            Visit(value as IPropertyIndexerExpression);
            Visit(value as IPropertyReferenceExpression);
            Visit(value as IQueryExpression);
            Visit(value as ISizeOfExpression);
            Visit(value as ISnippetExpression);
            Visit(value as IStackAllocateExpression);
            Visit(value as IThisReferenceExpression);
            Visit(value as ITryCastExpression);
            Visit(value as ITypedReferenceCreateExpression);
            Visit(value as ITypeReferenceExpression);
            Visit(value as IUnaryExpression);
            Visit(value as IValueOfTypedReferenceExpression);
            Visit(value as IVariableDeclarationExpression);
            Visit(value as IVariableReferenceExpression);
        }
        
        public void Visit(IExpressionCollection value)
        {
            if (value == null || value.Count == 0)
                return;

            WriteStartElement("IExpressionCollection");
            
            foreach (IExpression exp in value)
            {
                Visit(exp);
            }
                        
            WriteEndElement();
        }
        
        public void Visit(IAddressDereferenceExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IAddressDereferenceExpression");

            WriteStartElement("Expression");
            Visit(value.Expression);
            WriteEndElement();

            WriteEndElement();
        }

        public void Visit(IAddressOfExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IAddressOfExpression");

            WriteStartElement("Expression");
            Visit(value.Expression);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(IAddressOutExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IAddressOutExpression");

            WriteStartElement("Expression");
            Visit(value.Expression);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(IAddressReferenceExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IAddressReferenceExpression");
            
            WriteStartElement("Expression");
            Visit(value.Expression);
            WriteEndElement();
            
            WriteEndElement();

        }

        public void Visit(IAnonymousMethodExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IAnonymousMethodExpression");

            WriteStartElement("Body");
            Manager.StatementVisitor.Visit(value.Body);
            WriteEndElement();

            WriteStartElement("DelegateType");
            Manager.MetadataVisitor.Visit(value.DelegateType);
            WriteEndElement();

            WriteStartElement("Parameters");
            Manager.MetadataVisitor.Visit(value.Parameters);
            WriteEndElement();

            WriteStartElement("ReturnType");
            Manager.MetadataVisitor.Visit(value.ReturnType);
            WriteEndElement();
            
            WriteEndElement();

        }

        public void Visit(IArgumentListExpression value)
        {
            if (value == null)
                return;
            
            WriteEmptyElement("IArgumentListExpression");
        }

        public void Visit(IArgumentReferenceExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IArgumentReferenceExpression");

            WriteStartElement("Parameter");
            Manager.MetadataVisitor.Visit(value.Parameter);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(IArrayCreateExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IArrayCreateExpression");

            WriteStartElement("Dimensions");
            Visit(value.Dimensions);
            WriteEndElement();

            WriteStartElement("Initializer");
            Visit(value.Initializer);
            WriteEndElement();

            WriteStartElement("Type");
            Manager.MetadataVisitor.Visit(value.Type);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(IArrayIndexerExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IArrayIndexerExpression");

            WriteStartElement("Indices");
            Visit(value.Indices);
            WriteEndElement();

            WriteStartElement("Target");
            Visit(value.Target);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(IAssignExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IAssignExpression");

            WriteStartElement("Expression");
            Visit(value.Expression);
            WriteEndElement();

            WriteStartElement("Target");
            Visit(value.Target);
            WriteEndElement();
                        
            WriteEndElement();
        }

        public void Visit(IBaseReferenceExpression value)
        {
            if (value == null)
                return;
            
            WriteEmptyElement("IBaseReferenceExpression");
        }

        public void Visit(IBinaryExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IBinaryExpression");

            WriteStartElement("Left");
            Visit(value.Left); 
            WriteEndElement();
            
            WriteElement("Operator", value.Operator.ToString());

            WriteStartElement("Right");
            Visit(value.Right);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(IBlockExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IBlockExpression");

            WriteStartElement("Expressions");
            Visit(value.Expressions);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(ICanCastExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("ICanCastExpression");

            WriteStartElement("Expression");
            Visit(value.Expression);
            WriteEndElement();

            WriteStartElement("TargetType");
            Manager.MetadataVisitor.Visit(value.TargetType);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(ICastExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("ICastExpression");

            WriteStartElement("Expression");
            Visit(value.Expression);
            WriteEndElement();

            WriteStartElement("TargetType");
            Manager.MetadataVisitor.Visit(value.TargetType);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(IConditionExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IConditionExpression");

            WriteStartElement("Condition");
            Visit(value.Condition);
            WriteEndElement();

            WriteStartElement("Else");
            Visit(value.Else);
            WriteEndElement();

            WriteStartElement("Then");
            Visit(value.Then);
            WriteEndElement();
                        
            WriteEndElement();
        }

        public void Visit(IDelegateCreateExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IDelegateCreateExpression");

            WriteStartElement("DelegateType");
            Manager.MetadataVisitor.Visit(value.DelegateType);
            WriteEndElement();

            WriteStartElement("Method");
            Manager.MetadataVisitor.Visit(value.Method);
            WriteEndElement();

            WriteStartElement("Target");
            Visit(value.Target);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(IDelegateInvokeExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IDelegateInvokeExpression");

            WriteStartElement("Arguments");
            Visit(value.Arguments);
            WriteEndElement();

            WriteStartElement("Target");
            Visit(value.Target);
            WriteEndElement();            
            
            WriteEndElement();
        }

        public void Visit(IEventReferenceExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IEventReferenceExpression");

            WriteStartElement("Event");
            Manager.MetadataVisitor.Visit(value.Event);
            WriteEndElement();

            WriteStartElement("Target");
            Visit(value.Target);
            WriteEndElement();

            
            WriteEndElement();
        }

        public void Visit(IFieldOfExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IFieldOfExpression");

            WriteStartElement("Field");
            Manager.MetadataVisitor.Visit(value.Field);
            WriteEndElement();

            WriteStartElement("Type");
            Manager.MetadataVisitor.Visit(value.Type);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(IFieldReferenceExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IFieldReferenceExpression");

            WriteStartElement("Field");
            Manager.MetadataVisitor.Visit(value.Field);
            WriteEndElement();

            WriteStartElement("Target");
            Visit(value.Target);
            WriteEndElement();

            WriteEndElement();
        }

        public void Visit(IGenericDefaultExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IGenericDefaultExpression");

            WriteStartElement("GenericArgument");
            Manager.MetadataVisitor.Visit(value.GenericArgument);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(ILambdaExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("ILambdaExpression");

            WriteStartElement("Body");
            Visit(value.Body);
            WriteEndElement();

            WriteStartElement("Parameters");
            Manager.ILVisitor.Visit(value.Parameters);
            WriteEndElement();
                       
            WriteEndElement();
        }

        public void Visit(ILiteralExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("ILiteralExpression");
            
            if (value.Value != null)
            {
                WriteElement("Value", value.Value.ToString());
            }
            else
            {
                WriteElement("Value", "null");
            }
                        
            WriteEndElement();
        }

        public void Visit(IMemberInitializerExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IMemberInitializerExpression");

            WriteStartElement("Member");
            Manager.MetadataVisitor.Visit(value.Member);
            WriteEndElement();

            WriteStartElement("Value");
            Visit(value.Value);
            WriteEndElement();
                        
            WriteEndElement();
        }

        public void Visit(IMethodInvokeExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IMethodInvokeExpression");
            
            WriteStartElement("Arguments");
            Visit(value.Arguments);
            WriteEndElement();

            WriteStartElement("Method");
            Visit(value.Method);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(IMethodOfExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IMethodOfExpression");

            WriteStartElement("Method");
            Manager.MetadataVisitor.Visit(value.Method);
            WriteEndElement();

            WriteStartElement("Type");
            Manager.MetadataVisitor.Visit(value.Type);
            WriteEndElement();
            
            WriteEndElement();

        }
        public void Visit(IMethodReferenceExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IMethodReferenceExpression");
            
            WriteStartElement("Method");
            Manager.MetadataVisitor.Visit(value.Method);
            WriteEndElement();

            WriteStartElement("Target");
            Visit(value.Target);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(INullCoalescingExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("INullCoalescingExpression");

            WriteStartElement("Condition");
            Visit(value.Condition);
            WriteEndElement();

            WriteStartElement("Expression");
            Visit(value.Expression);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(IObjectCreateExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IObjectCreateExpression");

            WriteStartElement("Arguments");
            Visit(value.Arguments);
            WriteEndElement();

            WriteStartElement("Constructor");
            Manager.MetadataVisitor.Visit(value.Constructor);
            WriteEndElement();

            WriteStartElement("Initializer");
            Visit(value.Initializer);
            WriteEndElement();

            WriteStartElement("Type");
            Manager.MetadataVisitor.Visit(value.Type);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(IPropertyIndexerExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IPropertyIndexerExpression");

            WriteStartElement("Indices");
            Visit(value.Indices);
            WriteEndElement();

            WriteStartElement("Target");
            Visit(value.Target);
            WriteEndElement();

            WriteEndElement();
        }

        public void Visit(IPropertyReferenceExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IPropertyReferenceExpression");

            WriteStartElement("Property");
            Manager.MetadataVisitor.Visit(value.Property);
            WriteEndElement();

            WriteStartElement("Target");
            Visit(value.Target);
            WriteEndElement();
            
            WriteEndElement();
        }
        public void Visit(IQueryExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IQueryExpression");

            WriteStartElement("Body");
            Manager.ILVisitor.Visit(value.Body);
            WriteEndElement();

            WriteStartElement("From");
            Manager.ILVisitor.Visit(value.From);
            WriteEndElement();
            
            WriteEndElement();
        }
        public void Visit(ISizeOfExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("ISizeOfExpression");

            WriteStartElement("Type");           
            Manager.MetadataVisitor.Visit(value.Type);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(ISnippetExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("ISnippetExpression");
            
            WriteElement("Value", value.Value);

            WriteEndElement();
        }
        public void Visit(IStackAllocateExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IStackAllocateExpression");

            WriteStartElement("Expression");
            Visit(value.Expression);
            WriteEndElement();

            WriteStartElement("Type");
            Manager.MetadataVisitor.Visit(value.Type);
            WriteEndElement();         
            
            WriteEndElement();
        }

        public void Visit(IThisReferenceExpression value)
        {
            if (value == null)
                return;

            WriteEmptyElement("IThisReferenceExpression");   
        }

        public void Visit(ITryCastExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("ITryCastExpression");

            WriteStartElement("Expression");
            Visit(value.Expression);
            WriteEndElement();

            WriteStartElement("TargetType");
            Manager.MetadataVisitor.Visit(value.TargetType);
            WriteEndElement();
                        
            WriteEndElement();
        }
        public void Visit(ITypedReferenceCreateExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("ITypedReferenceCreateExpression");

            WriteStartElement("Expression");
            Visit(value.Expression);
            WriteEndElement();
            
            WriteEndElement();
        }

        public void Visit(ITypeOfExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("ITypeOfExpression");

            WriteStartElement("Type");
            Manager.MetadataVisitor.Visit(value.Type);
            WriteEndElement();
            
            WriteEndElement();
        }
        public void Visit(ITypeOfTypedReferenceExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("ITypeOfTypedReferenceExpression");

            WriteStartElement("Expression");
            Visit(value.Expression);
            WriteEndElement();
            
            WriteEndElement();
        }
        public void Visit(ITypeReferenceExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("ITypeReferenceExpression");

            WriteStartElement("Type");
            Manager.MetadataVisitor.Visit(value.Type);
            WriteEndElement();
            
            WriteEndElement();
        }
        public void Visit(IUnaryExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IUnaryExpression");
            
            WriteStartElement("Expression");
            Visit(value.Expression);
            WriteEndElement();

            WriteElement("Operator", value.Operator.ToString());
                        
            WriteEndElement();
        }
        public void Visit(IValueOfTypedReferenceExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IValueOfTypedReferenceExpression");

            WriteStartElement("Expression");
            Visit(value.Expression);
            WriteEndElement();

            WriteStartElement("TargetType");
            Manager.MetadataVisitor.Visit(value.TargetType);
            WriteEndElement();
                        
            WriteEndElement();
        }
        public void Visit(IVariableDeclarationExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IVariableDeclarationExpression");

            WriteStartElement("Variable");
            Manager.ILVisitor.Visit(value.Variable);
            WriteEndElement();           
            
            WriteEndElement();
        }
        public void Visit(IVariableReferenceExpression value)
        {
            if (value == null)
                return;

            WriteStartElement("IVariableReferenceExpression");

            WriteStartElement("Variable");
            Manager.ILVisitor.Visit(value.Variable);
            WriteEndElement();
            
            WriteEndElement();
        }       
        
    }
}
